package cn.taketoday.live.service.impl;

import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.buf.HexUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Hashtable;
import java.util.Map;
import java.util.Map.Entry;

import cn.taketoday.live.client.WebSocketProxy;
import cn.taketoday.live.component.ThreadComponent;
import cn.taketoday.live.config.GlobalData;
import cn.taketoday.live.data.BarrageHeader;
import cn.taketoday.live.data.FristSecurityData;
import cn.taketoday.live.data.room.CheckTx;
import cn.taketoday.live.data.room.Room;
import cn.taketoday.live.data.room.RoomInit;
import cn.taketoday.live.data.server.Conf;
import cn.taketoday.live.file.GuardFileTools;
import cn.taketoday.live.handler.MessageHandler;
import cn.taketoday.live.http.BilibiliHttpRequests;
import cn.taketoday.live.http.HttpRoomData;
import cn.taketoday.live.service.ClientService;
import cn.taketoday.live.service.SettingsService;
import cn.taketoday.live.tools.CurrencyTools;
import cn.taketoday.live.utils.ByteUtils;

/**
 * @author BanqiJane
 */
@Service
public class ClientServiceImpl implements ClientService {
  private SettingsService setService;
  private ThreadComponent threadComponent;

  public void startConnService(long roomid) throws Exception {
    if (roomid < 1) {
      return;
    }
    RoomInit roomInit = HttpRoomData.httpGetRoomInit(roomid);
    if (roomInit.getShort_id() > 0) {
      GlobalData.SHORT_ROOM_ID = roomInit.getShort_id();
    }
    GlobalData.ROOM_ID = roomInit.getRoom_id();
    Room room = HttpRoomData.httpGetRoomData(roomid);
    try {
      if (roomInit.getRoom_id() < 1 || roomInit.getRoom_id() == null) {
        return;
      }
    }
    catch (Exception e) {
      // TODO: handle exception
      return;
    }
    Conf conf = HttpRoomData.httpGetConf();
    if (conf == null) {
      return;
    }
    GlobalData.AU_ID = roomInit.getUid();
    GlobalData.FAN_SNUM = HttpRoomData.httpGetFollowersNum();

    GlobalData.WebSocketURL = CurrencyTools.GetWsUrl(conf.getHost_list());
    GlobalData.ANCHOR_NAME = room.getUname();
    GlobalData.lIVE_STATUS = roomInit.getLive_status();
    if (GlobalData.lIVE_STATUS == 1) {
      GlobalData.IS_ROOM_POPULARITY = true;
    }
    if (!StringUtils.isEmpty(GlobalData.USERCOOKIE)) {
      BilibiliHttpRequests.getUserBarrageMessage();
    }

    FristSecurityData fristSecurityData;
    WebSocketProxy webSocketProxy = new WebSocketProxy(GlobalData.WebSocketURL, room);
    GlobalData.setWebSocketProxy(webSocketProxy);
    if (!StringUtils.isEmpty(GlobalData.USERCOOKIE)) {
      fristSecurityData = new FristSecurityData(GlobalData.USER.getUid(),
                                                GlobalData.ROOM_ID,
                                                conf.getToken());
    }
    else {
      fristSecurityData = new FristSecurityData(GlobalData.ROOM_ID, conf.getToken());
    }

    webSocketProxy.send(fristSecurityData);
    webSocketProxy.send(HexUtils.fromHexString(GlobalData.heartByte));

    threadComponent.startHeartByteThread();
    setService.updateSettings(GlobalData.centerSetConf);
    CheckTx checkTx = null;
    // 登录发现天选屏蔽礼物
    if (GlobalData.centerSetConf != null && GlobalData.centerSetConf.getThank_gift().isIs_tx_shield()) {
      if (!StringUtils.isEmpty(GlobalData.USERCOOKIE)) {
        checkTx = HttpRoomData.httpGetCheckTX();
        if (checkTx != null) {
          if (!StringUtils.isEmpty(checkTx.getGift_name())) {
            if (checkTx.getTime() > 0) {
              threadComponent.startGiftShieldThread(checkTx.getGift_name(), checkTx.getTime());
            }
          }
        }
      }
    }
    // 登录发现天选屏蔽关注
    if (GlobalData.centerSetConf != null && GlobalData.centerSetConf.getFollow().isIs_tx_shield()) {
      if (!StringUtils.isEmpty(GlobalData.USERCOOKIE)) {
        if (checkTx == null) {
          checkTx = HttpRoomData.httpGetCheckTX();
        }
        if (checkTx != null) {
          if (checkTx.getTime() > 0) {
            // do something
//            threadComponent.startFollowShieldThread(checkTx.getTime());
          }
        }
      }
    }
    // 登录发现天选屏蔽欢迎
    if (GlobalData.centerSetConf != null && GlobalData.centerSetConf.getWelcome().isIs_tx_shield()) {
      if (!StringUtils.isEmpty(GlobalData.USERCOOKIE)) {
        if (checkTx == null) {
          checkTx = HttpRoomData.httpGetCheckTX();
        }
        if (checkTx != null) {
          if (checkTx.getTime() > 0) {
            // do something
            threadComponent.startWelcomeShieldThread(checkTx.getTime());
          }
        }
      }
    }
    if (!StringUtils.isEmpty(GlobalData.USERCOOKIE)) {
      if (GlobalData.centerSetConf != null
              && GlobalData.centerSetConf.getThank_gift().isIs_guard_local()) {
        final Map<Long, String> read = GuardFileTools.read();
        if (read.isEmpty()) {
          Hashtable<Long, String> guards = HttpRoomData.httpGetGuardList();
          if (guards != null && guards.size() > 0) {
            for (Entry<Long, String> entry : guards.entrySet()) {
              GuardFileTools.write(entry.getKey() + "," + entry.getValue());
            }
          }
          if (guards != null) {
            guards.clear();
          }
        }
      }
    }
    room = null;
    roomInit = null;
    conf = null;
  }

  public void reConnService() throws Exception {
    if (!GlobalData.webSocketProxy.isOpen()) {
      threadComponent.closeHeartByteThread();
      threadComponent.closeUserOnlineThread();
      threadComponent.closeAdvertThread();
      threadComponent.closeSendBarrageThread();
      threadComponent.closeLogThread();
      threadComponent.closeGiftShieldThread();
      threadComponent.closeFollowShieldThread();
      threadComponent.closeWelcomeShieldThread();
      threadComponent.closeAutoReplyThread();
      threadComponent.closeSmallHeartThread();
      threadComponent.disableMessageHandler();
      RoomInit roomInit = HttpRoomData.httpGetRoomInit(GlobalData.ROOM_ID);
      Room room = HttpRoomData.httpGetRoomData(GlobalData.ROOM_ID);
      try {
        if (roomInit.getRoom_id() < 1 || roomInit.getRoom_id() == null) {
          return;
        }
      }
      catch (Exception e) {
        // TODO: handle exception
        return;
      }
      if (roomInit.getShort_id() > 0) {
        GlobalData.SHORT_ROOM_ID = roomInit.getShort_id();
      }
      GlobalData.ROOM_ID = roomInit.getRoom_id();
      Conf conf = HttpRoomData.httpGetConf();
      if (conf == null) {
        return;
      }
      GlobalData.AU_ID = roomInit.getUid();
      GlobalData.FAN_SNUM = HttpRoomData.httpGetFollowersNum();

      GlobalData.WebSocketURL = CurrencyTools.GetWsUrl(conf.getHost_list());

      GlobalData.ANCHOR_NAME = room.getUname();
      GlobalData.lIVE_STATUS = roomInit.getLive_status();
      if (GlobalData.lIVE_STATUS == 1) {
        GlobalData.IS_ROOM_POPULARITY = true;
      }
      if (!StringUtils.isEmpty(GlobalData.USERCOOKIE)) {
        BilibiliHttpRequests.getUserBarrageMessage();
      }
      FristSecurityData fristSecurityData = null;
      GlobalData.webSocketProxy = new WebSocketProxy(GlobalData.WebSocketURL, room);
      if (!StringUtils.isEmpty(GlobalData.USERCOOKIE)) {
        fristSecurityData = new FristSecurityData(GlobalData.USER.getUid(), GlobalData.ROOM_ID,
                                                  conf.getToken());
      }
      else {
        fristSecurityData = new FristSecurityData(GlobalData.ROOM_ID, conf.getToken());
      }

      final BarrageHeader barrageHeader = new BarrageHeader(
              fristSecurityData.toJSON().getBytes().length + GlobalData.packageHeadLength,
              GlobalData.packageHeadLength,
              GlobalData.packageVersion,
              GlobalData.firstPackageType,
              GlobalData.packageOther
      );

      byte[] byte_1 = MessageHandler.toBytes(barrageHeader);
      byte[] byte_2 = fristSecurityData.toJSON().getBytes();
      byte[] req = ByteUtils.mergeBytes(byte_1, byte_2);
      GlobalData.webSocketProxy.send(req);
      GlobalData.webSocketProxy.send(HexUtils.fromHexString(GlobalData.heartByte));
      threadComponent.startHeartByteThread();
      if (GlobalData.webSocketProxy.isOpen()) {
        setService.updateSettings(GlobalData.centerSetConf);
      }
    }
  }

  public boolean closeConnService() {
    boolean flag = false;
    if (GlobalData.webSocketProxy != null) {
      if (GlobalData.webSocketProxy.isOpen()) {
        synchronized(GlobalData.webSocketProxy) {
          GlobalData.webSocketProxy.close();
          try {
            GlobalData.webSocketProxy.closeBlocking();
          }
          catch (InterruptedException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
          }
          GlobalData.webSocketProxy.closeConnection(1000, "手动关闭");
          GlobalData.webSocketProxy = null;
        }
        threadComponent.closeHeartByteThread();
        threadComponent.closeUserOnlineThread();
        threadComponent.closeAdvertThread();
        threadComponent.closeSendBarrageThread();
        threadComponent.closeLogThread();
        threadComponent.closeGiftShieldThread();
        threadComponent.closeFollowShieldThread();
        threadComponent.closeWelcomeShieldThread();
        threadComponent.closeAutoReplyThread();
        threadComponent.closeSmallHeartThread();
        threadComponent.disableMessageHandler();
        GlobalData.SHIELDGIFTNAME = null;
        GlobalData.thankGiftConcurrentHashMap.clear();
        GlobalData.logString.clear();
        GlobalData.IS_SHIELD_WELCOME = false;
        GlobalData.IS_SHIELD_FOLLOW = false;
        GlobalData.ROOM_ID = null;
        GlobalData.ANCHOR_NAME = null;
        GlobalData.AU_ID = null;
        GlobalData.FAN_SNUM = null;
        GlobalData.SHORT_ROOM_ID = null;
        GlobalData.lIVE_STATUS = 0;
        GlobalData.ROOM_POPULARITY = 1L;
        if (null == GlobalData.webSocketProxy || !GlobalData.webSocketProxy.isOpen()) {
          flag = true;
        }
      }
      else {
        flag = true;
      }
    }
    return flag;
  }

  @Autowired
  public void setSetService(SettingsService setService) {
    this.setService = setService;
  }

  @Autowired
  public void setThreadComponent(ThreadComponent threadComponent) {
    this.threadComponent = threadComponent;
  }
}
